package userService

import (
	"context"
	userDao "dev-assistant-backend/internal/dao/user"
	"dev-assistant-backend/utility/codemsg"
	userUtil "dev-assistant-backend/utility/user"
	"errors"

	jwtUtil "dev-assistant-backend/utility/jwt"

	"github.com/gogf/gf/v2/frame/g"
)

// Create 创建用户
func Create(ctx context.Context, userEntity *userDao.Entity) (*userDao.Entity, error) {
	// 对密码进行哈希处理
	hashedPassword, err := userUtil.HashPassword(userEntity.Password)
	if err != nil {
		g.Log().Line(true).Error(ctx, "hash password error", "error", err)
		return nil, err
	}

	// 更新实体中的密码为哈希值
	userEntity.Password = hashedPassword

	// 保存到数据库
	err = userDao.Create(ctx, g.DB(), userEntity)
	if err != nil {
		if errors.Is(err, codemsg.EmailAlreadyExistsErr) {
			g.Log().Line(true).Info(ctx, "email already exists", "email", userEntity.Email)
			return nil, codemsg.EmailAlreadyExistsErr
		}
		if errors.Is(err, codemsg.DuplicateEntryErr) {
			g.Log().Line(true).Info(ctx, "duplicate entry", "email", userEntity.Email)
			return nil, codemsg.DuplicateEntryErr
		}
		g.Log().Line(true).Error(ctx, "create user error", "error", err)
		return nil, err
	}

	resultEntity, err := userDao.GetById(ctx, g.DB(), userEntity.Id)
	if err != nil {
		g.Log().Line(true).Error(ctx, "get user by id error", "error", err)
		return nil, err
	}

	g.Log().Line(true).Info(ctx, "create user success", "user", resultEntity)
	return resultEntity, nil
}

//////////////////////////////////////////////////////////

func Login(ctx context.Context, email string, password string) (*userDao.Entity, string, error) {
	user, err := userDao.GetByEmail(ctx, g.DB(), email)
	if err != nil {
		if errors.Is(err, codemsg.UserNotFoundErr) {
			g.Log().Line(true).Info(ctx, "user not found", "email", email)
			return nil, "", codemsg.UserNotFoundErr
		}
		g.Log().Line(true).Error(ctx, "get user by email error", "error", err)
		return nil, "", err
	}

	// 使用安全的密码验证
	if !userUtil.CheckPassword(password, user.Password) {
		g.Log().Line(true).Info(ctx, "password is incorrect", "email", email)
		return nil, "", codemsg.PasswordIncorrectErr
	}

	if user.Status != userDao.StatusNormal {
		g.Log().Line(true).Info(ctx, "user is not active", "email", email)
		if user.Status == userDao.StatusBanned {
			return nil, "", codemsg.UserBannedErr
		} else if user.Status == userDao.StatusDeleted {
			return nil, "", codemsg.UserDeletedErr
		} else {
			return nil, "", codemsg.UserStatusInvalidErr
		}
	}

	jwt, err := jwtUtil.GeneratToken(
		ctx,
		jwtUtil.NewPayload(
			user.Id,
			user.Name,
			user.Email,
			user.Phone,
			user.Role,
			user.Status,
		),
	)
	if err != nil {
		g.Log().Line(true).Error(ctx, "generate jwt error", "error", err)
		return nil, "", err
	}

	return user, jwt, nil
}
